package com.shrcl.engineerprocess.domain.impl;

import com.google.common.base.Objects;
import com.shrcl.engineerprocess.domain.ActorsDAO;
import com.shrcl.engineerprocess.domain.CostEstimationProcesss;
import com.shrcl.engineerprocess.domain.CreateEngineerProjectTask;
import com.shrcl.engineerprocess.domain.Engineer;
import com.shrcl.engineerprocess.domain.EngineerCostEstimation;
import com.shrcl.engineerprocess.domain.EngineerCostEstimationDocument;
import com.shrcl.engineerprocess.domain.EngineerCostEstimationStatus;
import com.shrcl.engineerprocess.domain.EngineerProjectInitNotification;
import com.shrcl.engineerprocess.domain.EngineerProjectInitNotificationDAO;
import com.shrcl.engineerprocess.domain.ServiceEstimateInfo;
import com.shrcl.engineerprocess.domain.ServiceRequestInfo;
import com.shrcl.engineerprocess.domain.TSCManCostCalc;
import com.shrcl.engineerprocess.domain.TSCServiceTypeDefinition;
import com.shrcl.engineerprocess.domain.impl.CostEstimationProcesssImpl;
import com.shrcl.engineerprocess.domain.impl.CreateEngineerProjectTaskImpl;
import com.shrcl.engineerprocess.domain.impl.EngineerCostEstimationDocumentImpl;
import com.shrcl.engineerprocess.domain.impl.EngineerImpl;
import com.shrcl.engineerprocess.domain.impl.TSCManCostCalcImpl;
import com.shrcl.engineerprocess.domain.impl.TSCServiceTypeDefinitionImpl;
import com.shrcl.engineerprocess.domain.proxy.EngineerCostEstimationProxy;
import com.shrct.businessprocess.organization.RCEmployee;
import com.shrct.businessprocess.project.RCProject;
import com.shrct.businessprocess.project.impl.RCProjectImpl;
import com.uniquesoft.uidl.validation.Validates;
import edu.fudan.langlab.domain.document.IDocument;
import edu.fudan.langlab.domain.statemachine.ModelObjectLogService;
import edu.fudan.langlab.domain.task.TSKTask;
import edu.fudan.langlab.domain.task.TSKTaskDAO;
import edu.fudan.langlab.domain.task.TSKTaskOwner;
import edu.fudan.langlab.domain.workflow.BusinessProcess;
import edu.fudan.langlab.domain.workflow.impl.BusinessProcessImpl;
import edu.fudan.mylang.pf.BaseModelObject;
import edu.fudan.mylang.pf.IObjectFactory;
import edu.fudan.mylang.utils.DateUtil;
import java.util.Collection;
import java.util.Date;
import javax.persistence.AssociationOverride;
import javax.persistence.AssociationOverrides;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.eclipse.xtext.xbase.lib.ObjectExtensions;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
import org.hibernate.annotations.DiscriminatorOptions;
import org.springframework.beans.factory.BeanFactory;

@Entity
@DiscriminatorValue("ENGINEERCOSTESTIMATION_TYPE")
@DiscriminatorOptions(force = true)
@DiscriminatorColumn(length = 64)
@Table(name = "engineercostestimation")
public class EngineerCostEstimationImpl extends BaseModelObject implements EngineerCostEstimation {
  public EngineerCostEstimationImpl() {
    super();
  }
  
  private EngineerCostEstimationStatus Status;
  
  public EngineerCostEstimationStatus getStatus() {
    return this.Status;
  }
  
  private ModelObjectLogService getModelObjectLogService() {
    return getBeanFactory().getBean(ModelObjectLogService.class);
  }
  
  private void _start() {
    TSCServiceTypeDefinition tSCServiceTypeDefinition=TSCServiceTypeDefinitionImpl.create(getObjectFactory());
    final Procedure1<TSCServiceTypeDefinition> _function = new Procedure1<TSCServiceTypeDefinition>() {
        public void apply(final TSCServiceTypeDefinition it) {
          it.init();
        }
      };
    TSCServiceTypeDefinition _doubleArrow = ObjectExtensions.<TSCServiceTypeDefinition>operator_doubleArrow(tSCServiceTypeDefinition, _function);
    this.serviceTypes = _doubleArrow;TSCManCostCalc tSCManCostCalc=TSCManCostCalcImpl.create(getObjectFactory());
    final Procedure1<TSCManCostCalc> _function_1 = new Procedure1<TSCManCostCalc>() {
        public void apply(final TSCManCostCalc it) {
          it.init();
        }
      };
    TSCManCostCalc _doubleArrow_1 = ObjectExtensions.<TSCManCostCalc>operator_doubleArrow(tSCManCostCalc, _function_1);
    this.manCostCalc = _doubleArrow_1;
    Status=EngineerCostEstimationStatus.created;
  }
  
  public void start() {
    if(Status==null){
    	_start();
    	getModelObjectLogService().createLog(this,"Status","Start");
    	getBeanFactory().getBean(com.shrcl.engineerprocess.domain.events.EngineerCostEstimationEventsManager.class).fireStarted(this);					
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException("allready started");
    }
  }
  
  private void _submit() {
    
    IObjectFactory _objectFactory = this.getObjectFactory();
    final CostEstimationProcesss p = CostEstimationProcesssImpl.create(_objectFactory);
    p.start(this);
    Status=EngineerCostEstimationStatus.estimating;
  }
  
  public void submit() {
    if(Status==EngineerCostEstimationStatus.created){
    	_submit();
    	getModelObjectLogService().createLog(this,"Status","submit");
    	getBeanFactory().getBean(com.shrcl.engineerprocess.domain.events.EngineerCostEstimationEventsManager.class).fireSubmit(this);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  private void _approve() {
    
    Status=EngineerCostEstimationStatus.approved;
  }
  
  public void approve() {
    if(Status==EngineerCostEstimationStatus.estimating){
    	_approve();
    	getModelObjectLogService().createLog(this,"Status","approve");
    	getBeanFactory().getBean(com.shrcl.engineerprocess.domain.events.EngineerCostEstimationEventsManager.class).fireApprove(this);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  private void _connectToCBD(final RCProject project) {
    
    this.project = project;
    project.setIsConnected(Boolean.valueOf(true));
    Status=EngineerCostEstimationStatus.CBDConnected;
  }
  
  public void connectToCBD(final RCProject project) {
    if(Status==EngineerCostEstimationStatus.approved){
    	_connectToCBD(project);
    	getModelObjectLogService().createLog(this,"Status","connectToCBD");
    	getBeanFactory().getBean(com.shrcl.engineerprocess.domain.events.EngineerCostEstimationEventsManager.class).fireConnectToCBD(this,project);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  private void _cBDKickOff() {
    
    this.newCreateEngineerProjectTask();
    this.sendEngineerProjectNotification();
    Status=EngineerCostEstimationStatus.CBDKickedOff;
  }
  
  public void cBDKickOff() {
    if(Status==EngineerCostEstimationStatus.CBDConnected){
    	_cBDKickOff();
    	getModelObjectLogService().createLog(this,"Status","CBDKickOff");
    	getBeanFactory().getBean(com.shrcl.engineerprocess.domain.events.EngineerCostEstimationEventsManager.class).fireCBDKickOff(this);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  private void _engineerProjectKickOffNotify() {
    
    Status=EngineerCostEstimationStatus.ServiceProjectKickedOffNotified;
  }
  
  public void engineerProjectKickOffNotify() {
    if(Status==EngineerCostEstimationStatus.CBDKickedOff){
    	_engineerProjectKickOffNotify();
    	getModelObjectLogService().createLog(this,"Status","engineerProjectKickOffNotify");
    	getBeanFactory().getBean(com.shrcl.engineerprocess.domain.events.EngineerCostEstimationEventsManager.class).fireEngineerProjectKickOffNotify(this);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  public Boolean isCreated() {
    return com.shrcl.engineerprocess.domain.EngineerCostEstimationStatus.created==Status;
  }
  
  public Boolean isEstimating() {
    return com.shrcl.engineerprocess.domain.EngineerCostEstimationStatus.estimating==Status;
  }
  
  public Boolean isApproved() {
    return com.shrcl.engineerprocess.domain.EngineerCostEstimationStatus.approved==Status;
  }
  
  public Boolean isCBDConnected() {
    return com.shrcl.engineerprocess.domain.EngineerCostEstimationStatus.CBDConnected==Status;
  }
  
  public Boolean isCBDKickedOff() {
    return com.shrcl.engineerprocess.domain.EngineerCostEstimationStatus.CBDKickedOff==Status;
  }
  
  public Boolean isServiceProjectKickedOffNotified() {
    return com.shrcl.engineerprocess.domain.EngineerCostEstimationStatus.ServiceProjectKickedOffNotified==Status;
  }
  
  private String name;
  
  public String getName() {
    return this.name;
  }
  
  public EngineerCostEstimation setName(final String name) {
    this.name = name;
    return this;			
    
  }
  
  private String costEstID;
  
  public String getCostEstID() {
    return this.costEstID;
  }
  
  public EngineerCostEstimation setCostEstID(final String costEstID) {
    this.costEstID = costEstID;
    return this;			
    
  }
  
  @Embedded
  @AttributeOverrides(value = { @AttributeOverride(name = "reqeustInfoName", column = @Column(name = "requestInfo_reqeustInfoName") ), @AttributeOverride(name = "projectName", column = @Column(name = "requestInfo_projectName") ), @AttributeOverride(name = "contact", column = @Column(name = "requestInfo_contact") ), @AttributeOverride(name = "phoneNumber", column = @Column(name = "requestInfo_phoneNumber") ), @AttributeOverride(name = "email", column = @Column(name = "requestInfo_email") ), @AttributeOverride(name = "installationAddress", column = @Column(name = "requestInfo_installationAddress") ), @AttributeOverride(name = "hasOnSiteService", column = @Column(name = "requestInfo_hasOnSiteService") ), @AttributeOverride(name = "deliveryDate", column = @Column(name = "requestInfo_deliveryDate") ), @AttributeOverride(name = "installationDate", column = @Column(name = "requestInfo_installationDate") ), @AttributeOverride(name = "plannedDays", column = @Column(name = "requestInfo_plannedDays") ), @AttributeOverride(name = "guarranteeYears", column = @Column(name = "requestInfo_guarranteeYears") ), @AttributeOverride(name = "preSaleProposal", column = @Column(name = "requestInfo_preSaleProposal") ), @AttributeOverride(name = "outSourcingService", column = @Column(name = "requestInfo_outSourcingService") ), @AttributeOverride(name = "isOutSourcingService", column = @Column(name = "requestInfo_isOutSourcingService") ), @AttributeOverride(name = "isRequiredEngineerAssistant", column = @Column(name = "requestInfo_isRequiredEngineerAssistant") ), @AttributeOverride(name = "serviceBrand", column = @Column(name = "requestInfo_serviceBrand") ), @AttributeOverride(name = "outSourcingPhone", column = @Column(name = "requestInfo_outSourcingPhone") ), @AttributeOverride(name = "workaround", column = @Column(name = "requestInfo_workaround") ) } )
  @AssociationOverrides(value = { @AssociationOverride(name = "customer", joinColumns = @JoinColumn(name = "requestInfo_customer") ), @AssociationOverride(name = "salesMan", joinColumns = @JoinColumn(name = "requestInfo_salesMan") ), @AssociationOverride(name = "preSaleEngineer", joinColumns = @JoinColumn(name = "requestInfo_preSaleEngineer") ), @AssociationOverride(name = "deviceBrand", joinColumns = @JoinColumn(name = "requestInfo_deviceBrand") ) } )
  private ServiceRequestInfo requestInfo = com.shrcl.engineerprocess.domain.ServiceRequestInfo.create();
  
  public ServiceRequestInfo getRequestInfo() {
    return this.requestInfo;
  }
  
  public EngineerCostEstimation setRequestInfo(final ServiceRequestInfo requestInfo) {
    this.requestInfo = requestInfo;
    return this;			
    
  }
  
  @Embedded
  @AttributeOverrides(value = { @AttributeOverride(name = "estInfoName", column = @Column(name = "estimateInfo_estInfoName") ), @AttributeOverride(name = "tscCategory", column = @Column(name = "estimateInfo_tscCategory") ), @AttributeOverride(name = "workaround", column = @Column(name = "estimateInfo_workaround") ) } )
  @AssociationOverrides(value = @AssociationOverride(name = "customerServiceManager", joinColumns = @JoinColumn(name = "estimateInfo_customerServiceManager") ) )
  private ServiceEstimateInfo estimateInfo = com.shrcl.engineerprocess.domain.ServiceEstimateInfo.create();
  
  public ServiceEstimateInfo getEstimateInfo() {
    return this.estimateInfo;
  }
  
  public EngineerCostEstimation setEstimateInfo(final ServiceEstimateInfo estimateInfo) {
    this.estimateInfo = estimateInfo;
    return this;			
    
  }
  
  @JoinColumn(name = "serviceTypes_id")
  @OneToOne(targetEntity = TSCServiceTypeDefinitionImpl.class, cascade = CascadeType.ALL)
  private TSCServiceTypeDefinition serviceTypes;
  
  public TSCServiceTypeDefinition getServiceTypes() {
    return this.serviceTypes;
  }
  
  public EngineerCostEstimation setServiceTypes(final TSCServiceTypeDefinition serviceTypes) {
    this.serviceTypes = serviceTypes;
    return this;			
    
  }
  
  @JoinColumn(name = "manCostCalc_id")
  @OneToOne(targetEntity = TSCManCostCalcImpl.class, cascade = CascadeType.ALL)
  private TSCManCostCalc manCostCalc;
  
  public TSCManCostCalc getManCostCalc() {
    return this.manCostCalc;
  }
  
  public EngineerCostEstimation setManCostCalc(final TSCManCostCalc manCostCalc) {
    this.manCostCalc = manCostCalc;
    return this;			
    
  }
  
  private Double finalCostEst;
  
  public Double getFinalCostEst() {
    return this.finalCostEst;
  }
  
  public EngineerCostEstimation setFinalCostEst(final Double finalCostEst) {
    this.finalCostEst = finalCostEst;
    return this;			
    
  }
  
  @JoinColumn(name = "project_id")
  @ManyToOne(targetEntity = RCProjectImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private RCProject project;
  
  public RCProject getProject() {
    return this.project;
  }
  
  public EngineerCostEstimation setProject(final RCProject project) {
    this.project = project;
    return this;			
    
  }
  
  @JoinColumn(name = "businessProcess_id")
  @ManyToOne(targetEntity = BusinessProcessImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private BusinessProcess businessProcess;
  
  public BusinessProcess getBusinessProcess() {
    return this.businessProcess;
  }
  
  public EngineerCostEstimation setBusinessProcess(final BusinessProcess businessProcess) {
    this.businessProcess = businessProcess;
    return this;			
    
  }
  
  @JoinColumn(name = "postSaleManager_id")
  @ManyToOne(targetEntity = EngineerImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private Engineer postSaleManager;
  
  public Engineer getPostSaleManager() {
    return this.postSaleManager;
  }
  
  public EngineerCostEstimation setPostSaleManager(final Engineer postSaleManager) {
    this.postSaleManager = postSaleManager;
    return this;			
    
  }
  
  @JoinColumn(name = "technicalAssistant_id")
  @ManyToOne(targetEntity = EngineerImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private Engineer technicalAssistant;
  
  public Engineer getTechnicalAssistant() {
    return this.technicalAssistant;
  }
  
  public EngineerCostEstimation setTechnicalAssistant(final Engineer technicalAssistant) {
    this.technicalAssistant = technicalAssistant;
    return this;			
    
  }
  
  @OneToMany(targetEntity = EngineerCostEstimationDocumentImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE }, mappedBy = "engineerCostEstimation")
  private Collection<EngineerCostEstimationDocument> documents = new java.util.ArrayList<com.shrcl.engineerprocess.domain.EngineerCostEstimationDocument>();;
  
  public Collection<EngineerCostEstimationDocument> getDocuments() {
    return this.documents;
  }
  
  public EngineerCostEstimationDocument createAndAddtoDocuments() {
    getDocuments().size();
    com.shrcl.engineerprocess.domain.EngineerCostEstimationDocument engineerCostEstimationDocument = new com.shrcl.engineerprocess.domain.impl.EngineerCostEstimationDocumentImpl(this);
    getObjectFactory().create(engineerCostEstimationDocument);
    getDocuments().add(engineerCostEstimationDocument);
    return engineerCostEstimationDocument;
    
  }
  
  public EngineerCostEstimationDocument createAndAddtoDocuments(final Procedure1<EngineerCostEstimationDocument> updater) {
    getDocuments().size();
    com.shrcl.engineerprocess.domain.EngineerCostEstimationDocument engineerCostEstimationDocument = new com.shrcl.engineerprocess.domain.impl.EngineerCostEstimationDocumentImpl(this);
    getObjectFactory().create(engineerCostEstimationDocument);
    getDocuments().add(engineerCostEstimationDocument);
    return engineerCostEstimationDocument;
    
  }
  
  public EngineerCostEstimation removeAllDocuments() {
    for(EngineerCostEstimationDocument obj : this.documents){
    	getObjectFactory().delete(obj);
    }
    this.documents.clear();
    return this;	
    
  }
  
  public EngineerCostEstimation removeFromDocuments(final EngineerCostEstimationDocument engineerCostEstimationDocument) {
    this.documents.remove(engineerCostEstimationDocument);
    getObjectFactory().delete(engineerCostEstimationDocument);
    return this;
    
  }
  
  private String comments;
  
  public String getComments() {
    return this.comments;
  }
  
  public EngineerCostEstimation setComments(final String comments) {
    this.comments = comments;
    return this;			
    
  }
  
  public IDocument createDocument(final Procedure1<? super IDocument> init) {
    EngineerCostEstimationDocument _createAndAddtoDocuments = this.createAndAddtoDocuments();
    final Procedure1<EngineerCostEstimationDocument> _function = new Procedure1<EngineerCostEstimationDocument>() {
        public void apply(final EngineerCostEstimationDocument it) {
          init.apply(it);
        }
      };
    EngineerCostEstimationDocument _doubleArrow = ObjectExtensions.<EngineerCostEstimationDocument>operator_doubleArrow(_createAndAddtoDocuments, _function);
    return _doubleArrow;
  }
  
  public void removeDocument(final IDocument document) {
    this.removeFromDocuments(((EngineerCostEstimationDocument) document));
  }
  
  public BusinessProcess getProcess() {
    return this.businessProcess;
  }
  
  public String getEntityName() {
    String _projectName = this.requestInfo.getProjectName();
    return _projectName;
  }
  
  private void newCreateEngineerProjectTask() {
    BeanFactory _beanFactory = this.getBeanFactory();
    final TSKTaskDAO taskDAO = _beanFactory.<TSKTaskDAO>getBean(TSKTaskDAO.class);
    BeanFactory _beanFactory_1 = this.getBeanFactory();
    final ActorsDAO actorsDAO = _beanFactory_1.<ActorsDAO>getBean(ActorsDAO.class);
    RCEmployee _employee = this.postSaleManager==null?(RCEmployee)null:this.postSaleManager.getEmployee();
    final TSKTaskOwner tskOwner = actorsDAO.asTSKTaskOwner(_employee);
    boolean _notEquals = (!Objects.equal(tskOwner, null));
    Validates.Assert(_notEquals, "\u552E\u540E\u7ECF\u7406\u4E0D\u80FD\u4E3A\u7A7A");
    final Procedure1<TSKTask> _function = new Procedure1<TSKTask>() {
        public void apply(final TSKTask it) {
          Date _now = DateUtil.now();
          it.setGenDate(_now);
          Date _now_1 = DateUtil.now();
          it.setStartTime(_now_1);
          it.start();
          it.startProcess();
        }
      };CreateEngineerProjectTask createEngineerProjectTask=CreateEngineerProjectTaskImpl.create(getObjectFactory());
    final Procedure1<CreateEngineerProjectTask> _function_1 = new Procedure1<CreateEngineerProjectTask>() {
        public void apply(final CreateEngineerProjectTask it) {
          it.setEngineerCostEstimation(EngineerCostEstimationImpl.this);
          it.addOwner(tskOwner);
        }
      };
    CreateEngineerProjectTask _doubleArrow = ObjectExtensions.<CreateEngineerProjectTask>operator_doubleArrow(createEngineerProjectTask, _function_1);
    taskDAO.createTask(_function, _doubleArrow);
  }
  
  private void sendEngineerProjectNotification() {
    BeanFactory _beanFactory = this.getBeanFactory();
    final EngineerProjectInitNotificationDAO engineerProjectInitNotificationDAO = _beanFactory.<EngineerProjectInitNotificationDAO>getBean(EngineerProjectInitNotificationDAO.class);
    boolean _notEquals = (!Objects.equal(this.postSaleManager, null));
    Validates.Assert(_notEquals, "\u552E\u540E\u7ECF\u7406\u4E0D\u80FD\u4E3A\u7A7A");
    final Procedure1<EngineerProjectInitNotification> _function = new Procedure1<EngineerProjectInitNotification>() {
        public void apply(final EngineerProjectInitNotification it) {
          it.setEngineerCostEstimation(EngineerCostEstimationImpl.this);
        }
      };
    EngineerProjectInitNotification _create = engineerProjectInitNotificationDAO.create(_function);
    _create.performNotify();
  }
  
  public static EngineerCostEstimation create(final IObjectFactory objectFactory) {
    com.shrcl.engineerprocess.domain.EngineerCostEstimation engineerCostEstimation = new com.shrcl.engineerprocess.domain.impl.EngineerCostEstimationImpl(
    );
    objectFactory.create(engineerCostEstimation);
    return engineerCostEstimation;			
    
  }
  
  public static EngineerCostEstimation createEngineerCostEstimationImpl(final IObjectFactory objectFactory, final Procedure1<EngineerCostEstimation> init) {
    com.shrcl.engineerprocess.domain.EngineerCostEstimation engineerCostEstimation = new com.shrcl.engineerprocess.domain.impl.EngineerCostEstimationImpl(
    );
    objectFactory.create(engineerCostEstimation);
    init.apply(engineerCostEstimation);
    
    return engineerCostEstimation;			
    
  }
  
  public EngineerCostEstimationProxy toProxy() {
    com.shrcl.engineerprocess.domain.proxy.EngineerCostEstimationProxy proxy = new com.shrcl.engineerprocess.domain.proxy.EngineerCostEstimationProxy();
    proxy.setId(this.getId());
    if(this instanceof edu.fudan.mylang.pf.INamedModelObject){
    	proxy.setName(((edu.fudan.mylang.pf.INamedModelObject)this).getEntityName());
    }
    proxy.setStatus(this.getStatus().name());
    return proxy;
    
  }
}
